{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python+Gurobi特殊資料結構\n",
    "*POLab*\n",
    "<br>\n",
    "*2017/10/30*\n",
    "<br>\n",
    "[【回到首頁】](https://github.com/PO-LAB/Python-Gurobi)\n",
    "#### ※參考資料https://wenku.baidu.com/view/2aa313d328ea81c758f5782b.html 、[Gurobi-Python Interface](https://www.gurobi.com/documentation/6.5/quickstart_windows/py_python_interface.html#section:Python)\n",
    "-----------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在GurobI的Python介面中，會經常使用下列的資料結構，前四者為Python原有的資料結構，tuplelist是Gurobi為Python介面客製化的結構，可使Python Gurobi在資料處理上更加有效率和靈活。\n",
    "### ● list(列表)\n",
    "### ● tuple(元組)\n",
    "### ● dictionary(字典)\n",
    "### ● list comprehension(列表解析)\n",
    "### ● tuplelist\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (一)Lists(列表) and Tuples(元組)\n",
    "- 兩者皆為**有序集合**，索引位置由<span style=\"color:red\">**’0’**</span>開始數起\n",
    "- 內部可放任何物件，ex:數字、字串、字典、列表、元組等\n",
    "- 都可以透過索引、切片取得內部物件\n",
    "\n",
    "### ● Lists(列表)\n",
    "\n",
    "- 以<span style=\"color:red\">\"[ ]\"</span>形成 <br>\n",
    "  ex.[‘Pen’,’Denver’,’New York’]<br>\n",
    "- 可以新增、刪除、修改內容"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "list\n"
     ]
    }
   ],
   "source": [
    "#創建一個list a\n",
    "a=[1,2,3,'list']\n",
    "#索引位置由0開始\n",
    "print a[0]\n",
    "print a[3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 'list', 4]\n"
     ]
    }
   ],
   "source": [
    "#利用append為list最後加入一個元素\n",
    "a.append(4)\n",
    "print a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 'list', 4]\n"
     ]
    }
   ],
   "source": [
    "#利用remove刪除list中符合條件的元素\n",
    "a.remove(3)\n",
    "print a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "### ● tuple(元組)\n",
    "\n",
    "- 以<span style=\"color:red\">\"()\"</span>形成 <br>\n",
    "  ex.(‘Pen’,’Denver’,’New York’) <br>\n",
    "- tuple是**不可變的**，一旦被建立就不能修改<br>\n",
    "- 由於不可變的特性，因此可利用tuples當成dictionaries的索引\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "tuple\n"
     ]
    }
   ],
   "source": [
    "#創建一個tuple b\n",
    "b=(1,2,3,'tuple')\n",
    "#索引位置由0開始\n",
    "print b[0]\n",
    "print b[3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (二)Dictionaries(字典)and multidict"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ● Dictionaries(字典)\n",
    "- 使用<span style=\"color:red\">”{ }”</span>建立新的字典，字典以**「鍵值（key）:值(value)」**表示一個元素，並以冒號<span style=\"color:red\">’:’</span>來辨別鍵值與值<br>\n",
    "- 任一不可變的python物件皆可做為一個鍵值(key):<br>\n",
    "an integer、a oating-point number、a string、a tuple<br>\n",
    "- 透過’鍵值’來搜尋對應的’值’<br>\n",
    "- 在Python Gurobi 中可以透過字典來儲存gurobi的決策變數"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'zero': 0, 'two': 2, 'one': 1}\n"
     ]
    }
   ],
   "source": [
    "#建立一個字典對象values，並將各數值與相對應的鍵值(key)進行連結\n",
    "values={}\n",
    "values['zero']=0\n",
    "values['one']=1\n",
    "values['two']=2\n",
    "print values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'four': 4, 'five': 5, 'three': 3}\n"
     ]
    }
   ],
   "source": [
    "#透過初始化資料結構的方式建立字典\n",
    "numbers={'three':3,'four':4,'five':5}\n",
    "print numbers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "#利用鍵值(key)尋找所對應的值(value)\n",
    "print values['zero']\n",
    "print numbers['three']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ● multidict\n",
    "- 可以一次初始化一個或多個字典<br>\n",
    "- 參數是一個字典對象，每一個鍵值都對應一個長度為n的列表，該函數會將每一個列表拆成n個單項，並創造出n個字典<br>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from gurobipy import*\n",
    "names,lower,upper=multidict({'x':[0,1],'y':[1,2],'z':[0,3]})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['y', 'x', 'z']\n"
     ]
    }
   ],
   "source": [
    "#顯示共享鍵值列表\n",
    "print names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'y': 1, 'x': 0, 'z': 0}\n",
      "{'y': 2, 'x': 1, 'z': 3}\n"
     ]
    }
   ],
   "source": [
    "#顯示所創立的兩個字典\n",
    "print lower\n",
    "print upper"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (三)List comprehension(列表解析) and tuplelist\n",
    "### ● List comprehension(列表解析)\n",
    "- 以更簡潔的方式產生列表\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 4, 9, 16, 25]\n"
     ]
    }
   ],
   "source": [
    "print [x*x for x in [1,2,3,4,5]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 一個列表解析可包含多個for迴圈及if條件句\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]\n"
     ]
    }
   ],
   "source": [
    " print [(x,y) for x in range(3) for y in range(3) if x != y] "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ●  tuplelist\n",
    "- 能夠有效的在元組列表中檢索符合要求的子列表\n",
    "- 透過tuplelist中的**select**方法返回所有滿足特定條件的元組子集，此方法可以提高資料選擇的效率\n",
    "- 透過符號<span style=\"color:red\">‘*’</span>表示元組中相應位置元素配對成功的值\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<gurobi.tuplelist (2 tuples, 2 values each):\n",
      " ( 1 , 2 )\n",
      " ( 1 , 3 )\n",
      ">\n"
     ]
    }
   ],
   "source": [
    "from gurobipy import*\n",
    "l=tuplelist([(1,2),(1,3),(2,3),(2,4)])\n",
    "print l.select(1,'*')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<gurobi.tuplelist (2 tuples, 2 values each):\n",
      " ( 1 , 3 )\n",
      " ( 2 , 3 )\n",
      ">\n"
     ]
    }
   ],
   "source": [
    "print l.select('*',3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<gurobi.tuplelist (1 tuples, 2 values each):\n",
      " ( 1 , 3 )\n",
      ">\n"
     ]
    }
   ],
   "source": [
    "print l.select(1,3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<gurobi.tuplelist (4 tuples, 2 values each):\n",
      " ( 1 , 2 )\n",
      " ( 1 , 3 )\n",
      " ( 2 , 3 )\n",
      " ( 2 , 4 )\n",
      ">\n"
     ]
    }
   ],
   "source": [
    "print l.select('*','*')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ●  List comprehension v.s.tuplelist\n",
    "- 列表解析也可以達到與tuplelist同樣的搜尋結果，但是會較沒效率\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<gurobi.tuplelist (2 tuples, 2 values each):\n",
      " ( 1 , 2 )\n",
      " ( 1 , 3 )\n",
      ">\n"
     ]
    }
   ],
   "source": [
    "print l.select(1,'*')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(1, 2), (1, 3)]\n"
     ]
    }
   ],
   "source": [
    " print [(x,y) for x,y in l if x ==1] "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
